# Author: Chris Moyer
# OpenID version of the Authentication Handlers
import re
import sys
import os, os.path

import urllib

import marajo
from marajo.appengine.handlers import RequestHandler
from marajo.appengine.ext.webapp import status, template
from marajo.appengine.api.users import User

import logging
log = logging.getLogger("marajo.handlers.auth.openid")

# Open ID stuff
from openid.consumer import consumer
from openid.extensions import sreg
from openid.consumer.discover import DiscoveryFailure

import marajo.appengine.handlers.auth

marajo.config['handlers'].append( { "url": "/_ah/login", "handler": "marajo.appengine.handlers.auth.oid.LoginHandler" })
marajo.config['handlers'].append( { "url": "/_ah/verify", "handler": "marajo.appengine.handlers.auth.oid.VerifyHandler" })

class LoginHandler(RequestHandler):
    """
    Start off the login process
    """

    def get(self):
        template_values = {}
        template_values['application'] = marajo.config.get("application")
        template_values['fields'] = [ 
            {"name": "openid", "type": "text", "title": "OpenID"},
            {"name": "continue", "type": "hidden", "value": self.request.GET.get("continue", "/")},
        ]
        template_values['login_url'] = "/_ah/login"
        self.response.write(template.render('login.tmpl', template_values))

    def post(self):
        """
        Begin OpenID Authentication
        """
        openid_url = self.request.get("openid")
        c = consumer.Consumer(self.session, None)
        log.info("Login Attempt: %s" % openid_url)
        try:
            auth_request = c.begin(openid_url)
        except  DiscoveryFailure, e:
            self.response.write("OpenID Discovery failure: %s" % e)
            return

        sreg_request = sreg.SRegRequest(required=['email', 'nickname'])
        auth_request.addExtension(sreg_request)

        trust_root = self.request.host_url
        return_to = "%s/_ah/verify?continue=%s" % (self.request.host_url, urllib.quote_plus(self.request.get("continue")))

        url = auth_request.redirectURL(trust_root, return_to)
        return self.redirect(url)

class VerifyHandler(RequestHandler):
    """
    Verify the OpenID Token
    """

    def get(self):
        result = {}
        request_args = self.request.formDict()
        c = consumer.Consumer(self.session, None)
        return_to = "%s/_ah/verify?continue=%s" % (self.request.host_url, urllib.quote_plus(self.request.get("continue")))
        response = c.complete(request_args, return_to)
        sreg_response = {}
        if response.status == consumer.SUCCESS:
            sreg_response = sreg.SRegResponse.fromSuccessResponse(response)

        id = response.getDisplayIdentifier()
        user = User(id=id)
        for item in sreg_response.items():
            if item[0] in ['email', 'nickname']:
                setattr(user, item[0], item[1])
        self.session['user'] = user
        log.info("User Logged in: %s" % user.id)
        return self.redirect(self.request.get("continue"))


    def post(self):
        """
        OpenID 2 Allows you to use POST requests instead of GET requests, 
        but everything else is the same
        """
        return self.get()

